package com.collegeproject.weatherapp.fragments;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.TimeZone;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.os.Bundle;
import android.support.v4.app.ListFragment;
import android.util.Base64;
import android.util.Log;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.SearchView;
import android.widget.SearchView.OnQueryTextListener;
import android.widget.SimpleAdapter;
import android.widget.TextView;
import android.widget.Toast;

import com.collegeproject.weatherapp.R;
import com.collegeproject.weatherapp.StartActivity.FragmentListener;
import com.collegeproject.weatherapp.library.AsyncResponse;
import com.collegeproject.weatherapp.library.ConnectionDetector;
import com.collegeproject.weatherapp.library.DatabaseHandler;
import com.collegeproject.weatherapp.library.DateClass;
import com.collegeproject.weatherapp.library.HTTPfunctions;

public class PostsFragment extends ListFragment implements AsyncResponse,
		OnQueryTextListener {

	TextView error;
	ListView lv, clv;

	HTTPfunctions task;
	ArrayList<HashMap<String, String>> mylist;

	private static FragmentListener _listener;
	
	ConnectionDetector cd;

	// private static final String localURL = "http://10.0.2.2:8080/WeatherAppService.svc/rest/posts";
	private static final String postsURL = "http://x00068868.cloudapp.net/WeatherAppService/rest/posts";

	// private static final String localDeleteURL = "http://10.0.2.2:8080/WeatherAppService.svc/rest/post/";
	private static final String deleteURL = "http://x00068868.cloudapp.net/WeatherAppService/rest/post/";

	private static final String deleteUserURL = "http://x00068868.cloudapp.net/WeatherAppService/rest/user/";

	private static final String TAG = "PostsFragment";
	private static final String FILENAME = "PostsData.txt";
	private static final String ADMIN = "admin";
	private static final String DELETE = "DELETE";

	public static PostsFragment newInstance(FragmentListener listener) {
		PostsFragment f = new PostsFragment();
		_listener = listener;
		return f;
	}

	@Override
	public void onAttach(Activity activity) {
		// Toast.makeText(getActivity(), "Attaching Posts ... ",
		// Toast.LENGTH_SHORT).show();
		super.onAttach(activity);
	}

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setHasOptionsMenu(true);

	}

	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		return inflater.inflate(R.layout.listplaceholder, container, false);
	}

	@Override
	public void onActivityCreated(Bundle savedInstanceState) {
		super.onActivityCreated(savedInstanceState);
		error = (TextView) getView().findViewById(R.id.posts_error);
		cd = new ConnectionDetector(getActivity());
	}

	@Override
	public void onStart() {
		super.onStart();
		registerForContextMenu(getListView());

		File file = getActivity().getFileStreamPath(FILENAME);
		if (file.exists()) { // check for data in internal memory
			// Toast.makeText(getActivity(), "Start Posts file exits ... ",
			// Toast.LENGTH_SHORT).show();

			String cachedJson = getDataFromCache();
			setPosts(cachedJson); // fill list from cache file

			// Log.i(TAG + "Posts starts ", cachedJson.toString());
		} else {
			getPostsInfo(); // else call the web service
		}
	}

	@Override
	public void onResume() {
		// Toast.makeText(getActivity(), "Resuming Posts ... ",
		// Toast.LENGTH_SHORT)
		// .show();

		lv = getListView(); // list view clickable
		lv.setTextFilterEnabled(true);
		lv.setOnItemClickListener(new OnItemClickListener() {
			public void onItemClick(AdapterView<?> parent, View view,
					int position, long id) {
				@SuppressWarnings("unchecked")
				HashMap<String, String> o = (HashMap<String, String>) lv
						.getItemAtPosition(position);
				Toast.makeText(getActivity(),
						"Message was posted by " + o.get("username"),
						Toast.LENGTH_SHORT).show();
			}
		});
		super.onResume();
	}

	@Override
	public void onPause() {
		// Toast.makeText(getActivity(), "Pausing Posts", Toast.LENGTH_SHORT)
		// .show();
		super.onPause();
	}

	@Override
	public void onCreateContextMenu(ContextMenu menu, View v,
			ContextMenuInfo menuInfo) {
		super.onCreateContextMenu(menu, v, menuInfo);

		MenuInflater inflater = getActivity().getMenuInflater();
		inflater.inflate(R.menu.posts_context_menu, menu);

		DatabaseHandler db = new DatabaseHandler(getActivity());
		if (db.getRowCount() > 0) {
			HashMap<String, String> user = new HashMap<String, String>(
					db.getUserDetails());
			if (user.get("username").equals(ADMIN) == true) {
				menu.findItem(R.id.deleteUser).setVisible(true);

			}
		}

	}

	@Override
	public boolean onContextItemSelected(MenuItem item) {
		AdapterContextMenuInfo info = (AdapterContextMenuInfo) item
				.getMenuInfo();
		clv = getListView(); // list view
		@SuppressWarnings("unchecked")
		HashMap<String, String> o = (HashMap<String, String>) clv
				.getItemAtPosition((int) info.id);
		switch (item.getItemId()) {
		case R.id.deletePost:

			deletePost(o.get("postid"), o.get("username"));
			return true;

		case R.id.deleteUser:

			deleteUser(o.get("username"));
			return true;
		default:
			return super.onContextItemSelected(item);
		}
	}

	@Override
	public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
		inflater.inflate(R.menu.posts_fragment, menu);

		MenuItem menuItem = menu.findItem(R.id.item_posts_Search); // search
		// view for filtering posts
		SearchView searchView = (SearchView) menuItem.getActionView();
		setupSearchView(searchView);
		super.onCreateOptionsMenu(menu, inflater);
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case R.id.item_posts_Refresh:
			getPostsInfo();
			return true;
		default:
			return true;
		}
	}

	// HTTP Async task result
	@Override
	public void processFinish(String result) {
		try {
			JSONObject jObject = new JSONObject(result);
			if (jObject.has("Posts")) {
				setPosts(result);
			} else {
				processDeleteReply(result);
			}
		} catch (JSONException e) {
			Log.e(TAG, "Process finish " + e.getMessage());
		}

	}

	// call web service for posts
	private void getPostsInfo() {
		Boolean connected = cd.isConnectingToInternet();
		if (connected){ // check connection availability
			error.setVisibility(View.GONE);
			task = new HTTPfunctions(getActivity());
			task.execute(new String[] { postsURL });
			task.listener = this;
		} else {
			error.setText("No internet connection available");
			error.setVisibility(View.VISIBLE);
		}
	}

	// setting post to list view
	@SuppressLint("SimpleDateFormat")
	private void setPosts(String result) {
		mylist = new ArrayList<HashMap<String, String>>();
		try {
			JSONObject jObject = new JSONObject(result);
			int success = Integer.parseInt(jObject.getString("Success"));
			if (success == 0) { // success
				writeToCache(result); // save a cache of returned file

				JSONArray jArray = jObject.getJSONArray("Posts");

				// convert time from JSON to "seconds/days ago" format
				SimpleDateFormat dateFormat = new SimpleDateFormat(
						"MM/dd/yyyy hh:mm:ss aa");
				TimeZone tz = TimeZone.getTimeZone("GMT");
				dateFormat.setTimeZone(tz);

				Calendar c = Calendar.getInstance();
				String curentDate = dateFormat.format(c.getTime());

				for (int i = 0; i < jArray.length(); i++) {
					HashMap<String, String> map = new HashMap<String, String>();
					JSONObject e = jArray.getJSONObject(i);

					// date conversion
					String time = null;
					try {
						time = DateClass.getTimeDifference(
								e.getString("PostTime"), curentDate);
					} catch (ParseException e1) {
						Log.e(TAG, "Date Parsing " + e1.getMessage());
					}

					map.put("message", e.getString("PostMessage"));
					map.put("location", e.getString("PostLocation"));
					map.put("time", time);
					map.put("username", e.getString("UserName"));
					map.put("postid", e.getString("PostId"));
					mylist.add(map); // mapping values from JSON to Array list
				}
			} else {
				// Log.i("Setting Post", "No posts retrieved");
			}
		} catch (JSONException e) {
			Log.e(TAG + " Setting Posts ", "Error parsing data " + e.toString());
		}

		// adapter for list view in the view
		ListAdapter adapter = new SimpleAdapter(getActivity(), mylist,
				R.layout.listview_posts, new String[] { "message", "location",
						"time", "username" },
				new int[] { R.id.item_message, R.id.item_location,
						R.id.item_time, R.id.item_username });

		setListAdapter(adapter);
	}

	private void setupSearchView(SearchView mSearchView) { // search view setup
		mSearchView.setIconifiedByDefault(false);
		mSearchView.setSubmitButtonEnabled(false);
		mSearchView.setOnQueryTextListener(this);
		mSearchView.setQueryHint("Filter comments");
	}

	@Override
	public boolean onQueryTextChange(String newText) { // filter list view as
														// text is entered
		((SimpleAdapter) getListView().getAdapter()).getFilter()
				.filter(newText);
		return true;
	}

	@Override
	public boolean onQueryTextSubmit(String query) {
		return false;
	}

	@SuppressWarnings("static-access")
	private void writeToCache(String data) {
		try {

			FileOutputStream stream = null; // internal memory
			stream = getActivity().openFileOutput(FILENAME,
					getActivity().MODE_PRIVATE);
			stream.write(data.getBytes());
			stream.close();
			// Log.i("Post wrote data", data);
		} catch (FileNotFoundException e) {
			Log.e(TAG, e.getMessage());
		} catch (IOException e) {
			Log.e(TAG, e.getMessage());
		}
	}

	private String getDataFromCache() {
		String originalJson = null;
		try {

			FileInputStream fis; // read from internal memory
			fis = getActivity().openFileInput(FILENAME);
			StringBuffer fileContent = new StringBuffer("");

			byte[] buffer = new byte[1024];

			while (fis.read(buffer) != -1) {
				fileContent.append(new String(buffer));
			}
			originalJson = fileContent.toString();
			// Log.i("Post Read Json", originalJson);
		} catch (FileNotFoundException e) {
			Log.e(TAG + " Read from Cache", e.getMessage());
		} catch (IOException e) {
			Log.e(TAG + " Read from Cache", e.getMessage());
		}
		return originalJson;
	}
	private void deletePost(String postid, String messagePostedBy) {

		DatabaseHandler db = new DatabaseHandler(getActivity());
		if (db.getRowCount() > 0) { // check for any user logged in
			HashMap<String, String> user = new HashMap<String, String>(
					db.getUserDetails());

			if (user.get("username").equals(messagePostedBy)
					|| user.get("username").equals(ADMIN)) {

				// delete
				attemptDeletePost(postid, user.get("username"),
						user.get("password"));
			} else {
				// user didn't post the message
				Toast.makeText(getActivity(),
						"You don't have the right to delete this post",
						Toast.LENGTH_LONG).show();
			}
		} else {
			// not logged in
			Toast.makeText(getActivity(), "Login to delete comment",
					Toast.LENGTH_LONG).show();
		}
	}

	private void deleteUser(String user) {

		DatabaseHandler db = new DatabaseHandler(getActivity());
		if (db.getRowCount() > 0) { // check for any user logged in
			HashMap<String, String> loggedUser = new HashMap<String, String>(
					db.getUserDetails());

			if (loggedUser.get("username").equals(ADMIN)) {
				// delete
				attemptDeleteUser(loggedUser.get("username"),
						loggedUser.get("password"), user);
			} else {
				// not admin
				Toast.makeText(getActivity(),
						"You don't have the right to delete", Toast.LENGTH_LONG)
						.show();
			}
		} else {
			// not logged in
			Toast.makeText(getActivity(), "Login to delete", Toast.LENGTH_LONG)
					.show();
		}
	}

	// attempt to delete User
	private void attemptDeleteUser(String loggedname, String pass,
			String userTODelete) {
		Boolean connected = cd.isConnectingToInternet();
		if (connected) {
			error.setVisibility(View.GONE);
			try {
				String source = loggedname + ":" + pass;
				String base64 = Base64.encodeToString(source.getBytes("UTF-8"),
						Base64.URL_SAFE | Base64.NO_WRAP);

				String finalDeleteURL = deleteUserURL + userTODelete;

				HTTPfunctions task = new HTTPfunctions(getActivity(), DELETE,
						base64);
				task.listener = this;
				task.execute(new String[] { finalDeleteURL });

				// Log.i("url ", finalDeleteURL);
				// Log.i("base64 ", base64);
				// Log.i("source ", source);
			} catch (Exception e) {
				Log.e(TAG, "Attempt delete user" + e.getMessage());
			}

		} else {
			error.setText("No internet connection available");
			error.setVisibility(View.VISIBLE);
		}
	}

	// attempt to delete post
	private void attemptDeletePost(String postid, String username, String pass) {
		Boolean connected = cd.isConnectingToInternet();
		if (connected){
			error.setVisibility(View.GONE);
			try {
				String source = username + ":" + pass;
				String base64 = Base64.encodeToString(source.getBytes("UTF-8"),
						Base64.URL_SAFE | Base64.NO_WRAP);

				String finalDeleteURL = deleteURL + postid;

				HTTPfunctions task = new HTTPfunctions(getActivity(), DELETE,
						base64);
				task.listener = this;
				task.execute(new String[] { finalDeleteURL });

				// Log.i("url ", finalDeleteURL);
				// Log.i("base64 ", base64);
				// Log.i("source ", source);
			} catch (Exception e) {
				Log.e(TAG, "Attempt delete " + e.getMessage());
			}

		} else {
			error.setText("No internet connection available");
			error.setVisibility(View.VISIBLE);
		}
	}

	// process reply from delete operation
	private void processDeleteReply(String result) {
		try {
			JSONObject jObject = new JSONObject(result);
			int success = Integer.parseInt(jObject.getString("Success"));
			if (success == 0) {
				Toast.makeText(getActivity(),
						jObject.getString("ErrorMessage"), Toast.LENGTH_LONG)
						.show();
				getPostsInfo();
			} else {
				Toast.makeText(getActivity(),
						jObject.getString("ErrorMessage"), Toast.LENGTH_LONG)
						.show();
			}
		} catch (JSONException e) {
			Log.e(TAG + " Process Delete Reply ",
					"Error parsing data " + e.toString());
		}
	}

}
